//
// Created by cube on 2020/8/25.
//

#ifndef COMPILERDOMEA1_EVENTS_H
#define COMPILERDOMEA1_EVENTS_H

#include "../../Tools.h"
#include <memory>

#define LIB_EVENT LIB_TYPE_SUB_CLASS(Event::Type,Event)

namespace Lib {

    class EventLoop;

    struct Event {
        using Type = uint32_t;
        LIB_TYPE_BASE_CLASS(Type)
    public:
        Event(){}
        virtual ~Event(){}
        virtual void event(){}
        friend bool operator <(const Event& a,const Event& b)
        {return a.getType() < b.getType();}
        friend bool operator >(const Event& a,const Event& b)
        {return a.getType() > b.getType();}
    };

    //--------------------------------------------------------------------

    template <typename ...Args>
    struct DEvent : public Event{
        LIB_EVENT
        std::tuple<Args...> data;
        DEvent(Args ...args):data(std::tuple<Args...>(std::forward<Args>(args)...)){}
    };

    struct InvokeEvent : public Event {
        LIB_EVENT
        std::function<void()>   fun;
        InvokeEvent(const std::function<void()>& _fun):fun(_fun){}
        void event() override { fun(); }
    };

    template <typename ...Args>
    struct TimeEvent : public Event {
        LIB_EVENT
        std::chrono::microseconds time;
        std::tuple<Args...> data;
        TimeEvent(const std::chrono::microseconds& _time,Args ...args)
        :time(_time),data(std::tuple<Args...>(std::forward<Args>(args)...)){}
    };

    //------------------------------------------------------------------

    struct ObjectEvent : public Event {
        LIB_EVENT
        void* source_object;
        ObjectEvent(void* _source_object):source_object(_source_object){}
    };

    struct SignalEvent : public Event {
        LIB_EVENT
        std::function<void()>   fun;
        SignalEvent(const std::function<void()>& _fun):fun(_fun){}
        void event() override { fun(); }
    };

    struct SignalObjectEvent : public Event {
        LIB_EVENT
        std::function<void()>   fun;
        void* source_object;
        SignalObjectEvent(void* _source_object,std::function<void()> _fun)
        :source_object(_source_object),fun(_fun){}
    };

    struct StartEvent : public Event {LIB_EVENT};
    struct StopEvent : public Event {
        LIB_EVENT
        EventLoop*  loop;
        StopEvent(EventLoop* _loop):loop(_loop){}
        void event() override;
    };

#define LIB_EVENT_(T) struct T : public Event {LIB_EVENT};

}

#endif //COMPILERDOMEA1_EVENTS_H
